# coding=utf-8
"""
Author: Mr.夏末
@Function: 接口关键字封装
"""
import json,jsonpath,pymysql,requests,yaml

from class11_1.desc import relations
from common.Logger import logger, path


class Inter:
    """接口关键字类"""

    def __init__(self):
        """使用会话管理"""
        self.session = requests.session()
        # 保存结果
        self.jsonres = {}
        self.textres = ''
        # 关联字典
        self.relation_dict = {}
        # url前缀
        self.url = ''

    def seturl(self, url):
        """
        设置url前缀 主要是host信息
        :param url: 基准url
        """
        self.url = url
        return self.url

    @relations
    def get(self, url='', params=None):
        """
        get方法
        :param url: 接口地址
        :param params: 接口参数
        """
        # 处理url
        if url.startswith('http'):
            # 接口使用了完整url
            pass
        else:
            url = self.url + '/' + url

        # 处理参数
        params = self.__get_params_data(params)

        try:
            res = self.session.get(url, params=params)
        except Exception as e:
            logger.exception(e)
            self.textres = e.__str__()
            return False, self.textres
        # 对结果进行JSON解析
        try:
            self.jsonres = json.loads(res.text)
            return self.jsonres
        except:
            # 如果不能解析为JSON，就直接使用字符串
            self.jsonres = {}
            self.textres = res.text
            return self.textres

    @relations
    def post(self, url='', params=None):
        """
        post方法
        :param url: 接口地址
        :param params: 接口参数
        """
        # 处理url
        if url.startswith('http'):
            # 接口使用了完整url
            pass
        else:
            url = self.url + '/' + url

        #处理参数
        params = self.__get_params_data(params)

        try:
            res = self.session.post(url, data=params)
        except Exception as e:
            logger.exception(e)
            self.textres = e.__str__()
            return False, self.textres
        # 对结果进行JSON解析
        try:
            self.jsonres = json.loads(res.text)
            return self.jsonres
        except:
            # 如果不能解析为JSON，就直接使用字符串
            self.jsonres = {}
            self.textres = res.text
            return self.textres

    @relations
    def addheader(self, key='', value=''):
        """
        头里面添加键值对
        :param key: 键
        :param value: 值
        """
        self.session.headers[key] = value
        logger.info(self.session.headers)
        return self.session.headers

    def removeheader(self, key=''):
        """
        删除头
        :param key: 删除的键(如果是空或者空字符串，就清空头)
        :param value: 键的值
        """
        if key:
            try:
                self.session.headers.pop(key)
            except:
                pass
        else:
            self.session.headers = {}
        logger.info(self.session.headers)
        return self.session.headers

    def reauth(self):
        """重新授权"""
        if self.url:
            self.session.post(self.url + "/logout")
            res = self.session.post(self.url + "/auth")
            self.session.headers['token'] = res.json().get('token')
            logger.info(self.session.headers)
        else:
            self.session.post("http://www.testingedu.com.cn:8081/inter/HTTP/logout")
            res = self.session.post("http://www.testingedu.com.cn:8081/inter/HTTP/auth")
            self.session.headers['token'] = res.json().get('token')
            logger.info(self.session.headers)
        return self.session.headers

    @relations
    def savejson(self, json_path='', p_name=''):
        """
        从上一步请求里面保存一个键为某个参数
        :param key: 键名
        :param p_name: 参数名
        """
        if json_path:
            value = jsonpath.jsonpath(self.jsonres, json_path)
            if value:
                value = value[0]
            else:
                value = str(value)

            if p_name:
                self.relation_dict[p_name] = value
            else:
                self.relation_dict[json_path] = value
        else:
            # 如果我保存返回结果里面某个小json
            if p_name:
                for key in self.jsonres.get(p_name).keys():
                    self.relation_dict[key] = str(self.jsonres.get(key))
            else:
                for key in self.jsonres.keys():
                    self.relation_dict[key] = str(self.jsonres.get(key))
        return self.relation_dict

    @relations
    def assertequals(self, json_path='', value=''):
        """
        断言请求结果里面某个键的值是预期的value
        :param key: 断言的键
        :param value: 预期的值
        """
        actual_value = jsonpath.jsonpath(self.jsonres,json_path)
        if actual_value:
            actual_value = actual_value[0]

        if str(value) == str(actual_value):
            logger.info(f'实际结果: {actual_value},预期结果: {value}')
            logger.info("PASS")
            return True,"PASS"
        else:
            logger.info(f'实际结果: {actual_value},预期结果: {value}')
            logger.error("FAIL")
            return False,f"FAIL: {actual_value},{value}"

    @relations
    def assertcontains(self, json_path='', value=''):
        """
        断言请求结果里面某个键的值是预期的value
        :param key: 断言的键
        :param value: 预期的值
        """
        actual_value = jsonpath.jsonpath(self.jsonres, json_path)
        if actual_value:
            actual_value = actual_value[0]

        if str(value).__contains__(str(actual_value)):
            logger.info(f'实际结果: {actual_value},预期结果: {value}')
            logger.info("PASS")
            return True, "PASS"
        else:
            logger.info(f'实际结果: {actual_value},预期结果: {value}')
            logger.error("FAIL")
            return False, f"FAIL: {actual_value},{value}"

    def __get_params_data(self,params):
        """
        json/字典、url格式参数转字典
        :param params: 字符串参数
        """
        if params:
            params_dict = {}
            try:
                #先处理是不是字典
                params_dict = eval(params)
                return params_dict
            except:
                pass

            #再处理JSON字符串
            try:
                #先处理是不是JSON
                params_dict = json.loads(params)
                return params_dict
            except:
                pass

            # 切割键值对
            params = params.split('&')
            for p in params:
                i = p.find('=')
                if i > 0:
                    params_dict[p[:i]] = p[i + 1:]
                else:
                    params_dict[p] = None
            logger.info('参数'+ str(params_dict))
            return params_dict
        else:
            return None

    def exesql(self,sql=''):
        """
        执行SQL并返回查询结果
        :param sql: SQL语句
        """
        with open(file=path + "lib/conf.yml", mode='r', encoding="utf-8")as file:
            self.conf = yaml.safe_load(stream=file).get('mysql')

        self.sqlpath = path + 'lib\\' + self.conf['sqlpath']
        self.conf.pop('sqlpath')
        # 创建连接，执行语句的时候是在这个连接上执行
        connect = pymysql.connect(**self.conf)
        cursor = connect.cursor()
        # 执行单条语句的示例
        cursor.execute(sql)
        # 获取查询结果
        res = cursor.fetchall()
        # 关闭游标和连接
        cursor.close()
        connect.close()
        return res
